1. Field
The following relates generally to using ray tracing for rendering 2-D representations of 3-D scenes, and more specifically to aspects of programming and usage of software components for such ray tracing.
2. Related Art
Rendering photo-realistic 2-D images from 3-D scene descriptions with ray tracing is well-known in the computer graphics arts. Ray tracing usually involves obtaining a scene description composed of geometric shapes, which describe surfaces of structures in the scene, and can be called primitives. A common primitive shape is a triangle.
Virtual rays of light are traced into the scene from a view point (“a camera”); each ray is issued to travel through a respective pixel of the 2-D representation, on which that ray can have an effect. The rays are tested for intersection with scene primitives to identify a first intersected primitive for each ray, if any.
After identifying an intersection for a given ray, a shader associated with that primitive determines what happens next. For example, if the primitive is part of a mirror, then a reflection ray is issued to determine whether light is hitting the intersected point from a luminaire, or in more complicated situations, subsurface reflection, and scattering can be modeled, which may cause issuance of different rays to be intersection tested. By further example, if a surface of an object were rough, not smooth, then a shader for that object may issue rays to model a diffuse reflection on that surface. As such, finding an intersection between a ray and a primitive is a step in determining whether and what kind of light energy may reach a pixel by virtue of a given ray, since what light is hitting that primitive still needs to be determined.
Thus, most conventional algorithms build a tree of rays in flight when ray tracing a scene, where the tree continues along each branch until it leaves the scene or hits a luminaire that does not issue new rays. Then, for those branches that hit light emissive objects (“luminaires”), the branches are rolled up through the primitive intersections, determining along the way what effect each primitive intersection has on the light that hits it. Finally, a color and intensity of light for the originally issued camera ray can be determined and stored in the buffer.
This approach to ray tracing is called recursive ray tracing, and has long been a dominant implementation. It is attractive because its operations are described simply: the tree builds by recursively emitting rays to be tested in response to primitive intersections, while they are identified, then, the tree is closed (“rolled up”) by feeding results back up.
However, recursive ray tracing can be problematic for a variety of reasons. For example, a large amount of ray state must be maintained while ends of the tree are identified, since state for each ray dependent on an uncompleted branch of rays is stored. Also, a great deal of state for shaders that cannot complete, as they wait for downstream results, is usually stored on a stack. This is so, since rays are traced in order; for example, a child ray is not traced concurrently with a parent ray. The following describes non-recursive ray tracing strategies where state for such rays does not need to be stored, and systems, methods, and code for programmers and other developers to interface with systems and software implementing such strategies.